use crate::{JwtClaims, WebResponseSupportTrait};
use salvo::prelude::JwtAuthDepotExt;
use salvo::{handler, Depot, Request, Response};
use serde_json::Value;
use std::collections::HashMap;
use std::str::FromStr;
use std::sync::Arc;
use visit_dd_core::field::{VddField, FT_STRING};
use visit_dd_core::i18n_text::{E_ARG_BAD, E_ARG_MISS, E_NO_PERMISSION_FOR_ACTION};
use visit_dd_core::query::WebTreeNode;
use visit_dd_core::record::RecordRule;
use visit_dd_core::visit::{ShareRuleOfField, VisitGroup};
use visit_dd_core::{i18n, random_az_str, Astr, FieldId, JsonSupportTrait};
use visit_dd_db::field_db::FieldDbTrait;
use visit_dd_db::rust_rocksdb::WriteBatchWithTransaction;
use visit_dd_db::sqlx::SqlxDataStoreTrait;
use visit_dd_db::{field_db, ROCKSDB};
use visit_dd_db::{model_db, record_rule_db, visit_db};

/// 获取我的所有模型的标记
#[handler]
pub(crate) async fn g_tag_map(req: &mut Request, _depot: &mut Depot, res: &mut Response) {
    let model_id = req.param::<&str>("model-id").unwrap();
    let model_id = model_id.parse::<u64>().unwrap();
    let model_tag_map = model_db::m_select_tags_to_map(true, true, Some(model_id)).await;
    if model_tag_map.len() < 1 {
        res.error(i18n!(1017).as_ref());
    } else {
        res.ok(&model_tag_map);
    }
}

/// 获取私有的所有模型列表
#[handler]
pub(crate) async fn g_as_tree_with_tag(_req: &mut Request, depot: &mut Depot, res: &mut Response) {
    let jwt = &depot.jwt_auth_data::<JwtClaims>().unwrap().claims;
    let all_models = model_db::m_select_by_uid(&jwt.uid).await;
    let tags = model_db::m_select_tags_to_map(true, true, None).await;
    // let remote_keys = select_remote_keys(rocksdb);
    let mut tree_nodes = Vec::<WebTreeNode>::new();
    for model in all_models {
        // if x.store_id > 0 {
        //     if let Some(rk) = remote_keys.get(&x.id) {
        //         let mut tree_node = QueryableTarget::from_model_with_code(&x, &rk);
        //         tree_node.add_fields(&select_fields(rocksdb, x.id), &remote_keys);
        //         tree_nodes.push(tree_node);
        //     }
        // } else {
        if let Some(tag) = tags.get(&model.id) {
            //未设置标签的模型无法进行查询
            let mut tree_node = WebTreeNode::from_model_with_code(&model, tag);
            let schema = visit_dd_db::cache::get_schema(model.id).await.unwrap();
            tree_node.add_fields(&schema.fields, &tags);
            tree_nodes.push(tree_node);
        }
        // }
    }
    res.ok(&tree_nodes);
}

/// 检查上传的json格式
fn check_field_json(j: &Value) -> bool {
    j.has_useful_str("label")
        && j["modelId"].as_u64().is_some()
        && j["displayOrder"].as_i64().is_some()
        && j["fieldType"].as_u64().is_some()
}

/// 新建一个字段
#[handler]
pub(crate) async fn p_create_field(req: &mut Request, depot: &mut Depot, res: &mut Response) {
    let jwt = &depot.jwt_auth_data::<JwtClaims>().unwrap().claims;
    let j: Value = req.parse_body::<Value>().await.unwrap();
    if !check_field_json(&j) {
        res.error(i18n!(E_ARG_BAD).as_ref());
        return;
    }
    let model_id = j["modelId"].as_u64().unwrap();
    let schema = visit_dd_db::cache::get_schema(model_id).await.unwrap();
    if schema.model.store.is_some() {
        res.error(i18n!(1202).as_ref());
        return;
    }
    let mut field = VddField::new(
        model_id,
        j["displayOrder"].as_i64().unwrap() as i8,
        j["label"].as_str().unwrap(),
        j["fieldType"].as_u64().unwrap() as u16,
    );
    if let Err(msg) = field.update_form_json(&j) {
        res.error(&msg);
        return;
    }
    let other_fields = schema.fields.clone();
    if let Err(e) = field_db::f_check_with_brothers(&field, &other_fields).await {
        res.error(&e);
        return;
    }
    if let Err(e) = field.check_501(&other_fields).await {
        res.error(&e);
        return;
    }
    if let Err(e) = field_db::f_save(&field, &jwt.uid, false).await {
        res.error(&e);
        return;
    }
    res.ok(&field);
}

/// 修改一个字段定义
#[handler]
pub(crate) async fn p_change_field(req: &mut Request, depot: &mut Depot, res: &mut Response) {
    let jwt = &depot.jwt_auth_data::<JwtClaims>().unwrap().claims;
    let j: Value = req.parse_body::<Value>().await.unwrap();
    if !check_field_json(&j) || !j.has_useful_int("fieldId") {
        res.error(i18n!(E_ARG_BAD).as_ref());
        return;
    }
    let mut field = field_db::f_load(&FieldId(
        j["fieldId"].as_u64().expect(i18n!(E_ARG_BAD).as_ref()),
    ))
    .await;
    let old_type: u16 = field.field_type.as_ref().into();
    let old_multi = field.multi;
    let field = Arc::get_mut(&mut field).unwrap();
    if let Err(msg) = field.update_form_json(&j) {
        res.error(&msg);
        return;
    }
    let fv_count = field.count_values();
    let new_type: u16 = field.field_type.as_ref().into();
    if fv_count > 0 {
        if old_multi != field.multi && old_type != new_type {
            res.error("此列已有列值存在，不能同时修改字段的类型与多重值属性");
            return;
        }
        if new_type != FT_STRING && old_type != new_type {
            res.error("此列已有列值存在，不能讲列转成字符串以外的类型");
            return;
        }
    }
    let schema = visit_dd_db::cache::get_schema(field.model_id)
        .await
        .unwrap();
    //检查新的字段定义是否合规
    let mut other_fields = schema.fields.clone();
    other_fields.retain(|f| f.id != field.id);
    if let Err(e) = field_db::f_check_with_brothers(field, &other_fields).await {
        res.error(&e);
        return;
    }
    if let Err(e) = field.check_501(&other_fields).await {
        res.error(&e);
        return;
    }
    // 写入新的字段设置
    field_db::f_save(field, &jwt.uid, true).await.unwrap();
    // 检查并确保已经存在的字段值符合唯一性约束
    let mut batch = WriteBatchWithTransaction::<true>::default();
    if field.unique {
        let r = field_db::fit_unique_on_exist_records(&mut batch, &field);
        if let Err(e) = r {
            res.error(&e);
            return;
        }
    }
    if new_type == FT_STRING && new_type != old_type {
        field_db::fit_to_string_on_exist_records(&mut batch, &field.id);
    }
    match (old_multi, field.multi) {
        (false, true) => field_db::fit_s_to_m(&mut batch, &field.id),
        (true, false) => field_db::fit_m_to_s(&mut batch, &field.id),
        _ => {}
    }
    ROCKSDB.write(batch).unwrap();
    res.ok(&field);
}

/// 删除一个字段
#[handler]
pub(crate) async fn p_remove_field(req: &mut Request, depot: &mut Depot, res: &mut Response) {
    let jwt = &depot.jwt_auth_data::<JwtClaims>().unwrap().claims;
    let field_id = req
        .params()
        .get("field-id")
        .cloned()
        .expect(i18n!(E_ARG_MISS).as_ref());
    let field_id = u64::from_str(&field_id).expect(i18n!(E_ARG_BAD).as_ref());
    let field = field_db::f_load(&FieldId(field_id)).await;
    let model = model_db::m_load(field.model_id).await;
    if model.store.is_some() {
        res.error(i18n!(1202).as_ref());
        return;
    }
    let r = field_db::f_delete(&field, &jwt.uid).await;
    res.wrap(r);
}

/// 获取一个模型内包含的所有字段信息
#[handler]
pub(crate) async fn g_fields_in_model(req: &mut Request, depot: &mut Depot, res: &mut Response) {
    let jwt: &JwtClaims = &depot.jwt_auth_data::<JwtClaims>().unwrap().claims;
    let model_id = req.params().get("model-id").cloned().unwrap();
    let model_id = u64::from_str(&model_id).unwrap();
    let schema = visit_dd_db::cache::get_schema(model_id).await.unwrap();
    // 校验访问权限 允许作者与访问组成员访问
    let mut vg: Option<Arc<VisitGroup>> = None;
    if schema.model.uid != jwt.uid {
        vg = visit_db::vg_try_load_in_model_by_user(model_id, &jwt.uid).await;
        if vg.is_none() {
            res.error(i18n!(9002).as_ref());
            return;
        };
    }
    let mut fields = schema.fields.clone();
    if vg.is_some() {
        // 将限制展示的字段从候选字段列表中剔除
        let vg = vg.clone().unwrap();
        vg.rule_f.iter().for_each(|x| match x.as_ref() {
            ShareRuleOfField::SrfHide(field_ids) => {
                for fid in field_ids {
                    fields.retain(|field| field.id != *fid);
                }
            }
            _ => {}
        });
    }
    res.ok(&fields);
}

/// 重新从远程数据存储中导入字段定义
#[handler]
pub(crate) async fn p_re_import_fields(req: &mut Request, depot: &mut Depot, res: &mut Response) {
    let jwt = &depot.jwt_auth_data::<JwtClaims>().unwrap().claims;
    let model_id = req
        .params()
        .get("model-id")
        .expect(i18n!(E_ARG_MISS).as_ref());
    let model_id = u64::from_str(model_id).expect(i18n!(E_ARG_BAD).as_ref());
    let model = model_db::m_load(model_id).await;
    if model.uid != jwt.uid {
        res.error(i18n!(E_NO_PERMISSION_FOR_ACTION).as_ref());
        return;
    }
    if model.store.is_none() {
        res.error(i18n!(1020).as_ref());
        return;
    }
    let store = model.store.to_owned().unwrap();
    if !store.test_connection().await {
        res.error(i18n!(1201).as_ref());
        return;
    }
    // 先获取新一批字段成功
    let new_fields = store.import_fields(&model).await;
    // tracing::info!("{:?}", new_fields);
    // 开始删除旧的字段
    field_db::f_clear_in_model(model_id, &jwt.uid)
        .await
        .unwrap();
    // 保存新字段
    field_db::f_save_some(&new_fields, &jwt.uid).await.unwrap();
    //
    let mut tag_map = HashMap::<Astr, u64>::new();
    new_fields.iter().for_each(|field| {
        tag_map.insert(field.label.replace(":", "").into(), field.id.0);
    });
    // 校验模型标记是否被占用
    let m_tag = model.store.clone().unwrap().remote_key.to_string();
    let mut m_tag_unique = model_db::m_is_tag_unique(&m_tag, model_id).await;
    let mut tag_tail = String::new();
    while !m_tag_unique {
        tag_tail = random_az_str(6);
        m_tag_unique =
            model_db::m_is_tag_unique(&format!("{}_{}", m_tag, tag_tail), model_id).await;
    }
    let m_tag = format!("{}_{}", m_tag, tag_tail);
    let r = model_db::m_save_tags(&model, &m_tag, &tag_map).await;
    res.wrap(r);
}

///
#[handler]
pub(crate) async fn p_remove_rvr(req: &mut Request, depot: &mut Depot, res: &mut Response) {
    let jwt = &depot.jwt_auth_data::<JwtClaims>().unwrap().claims;
    let j: Value = req
        .parse_body::<Value>()
        .await
        .expect(i18n!(E_ARG_BAD).as_ref());
    let model_id = j["modelId"].as_u64().expect(i18n!(E_ARG_BAD).as_ref());
    let rule_id = j["id"].as_u64().expect(i18n!(E_ARG_BAD).as_ref());
    let r = record_rule_db::rr_delete_one(model_id, rule_id, &jwt.uid).await;
    res.wrap(r);
}

///
#[handler]
pub(crate) async fn p_save_rvr(req: &mut Request, depot: &mut Depot, res: &mut Response) {
    let jwt: &JwtClaims = &depot.jwt_auth_data::<JwtClaims>().unwrap().claims;
    let j: Value = req.parse_body::<Value>().await.unwrap();
    let model_id = j["modelId"].as_u64().expect(i18n!(E_ARG_BAD).as_ref());
    let rule = RecordRule::new(model_id, &j);
    let r = record_rule_db::rr_save(&rule, &jwt.uid).await;
    res.wrap(r);
}

///
#[handler]
pub(crate) async fn g_rvrs(req: &mut Request, _depot: &mut Depot, res: &mut Response) {
    let model_id = req.param::<String>("model-id").unwrap();
    let model_id = u64::from_str(&model_id).unwrap();
    let rules = record_rule_db::rr_select_in_model(model_id).await;
    res.ok(&rules);
}

///
#[handler]
pub(crate) async fn p_drop(req: &mut Request, _depot: &mut Depot, res: &mut Response) {
    let j: Value = req
        .parse_body::<Value>()
        .await
        .expect(i18n!(E_ARG_BAD).as_ref());
    let field_id = j["fid"].as_u64().expect(i18n!(E_ARG_BAD).as_ref());
    let ares = field_db::f_drop_from_trash(FieldId(field_id)).await;
    res.wrap(ares);
}
